package concurrent.c_005_AtomicXXX_CAS;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
 * https://www.cnblogs.com/jhxxb/p/11358272.html
 * Unsafe 是 sun.misc 包下的一个类，可以直接操作堆外内存，可以随意查看及修改 JVM 中运行时的数据，
 * 使 Java 语言拥有了类似 C 语言指针一样操作内存空间的能力。
 * Unsafe 的操作粒度不是类，而是内存地址和所对应的数据，增强了 Java 语言操作底层资源的能力。
 */
public class T04_HelloUnsafe {

    static class M {
        private M() {
        }

        int i = 0;
    }

    public static void main(String[] args) throws InstantiationException, NoSuchFieldException {
        Unsafe unsafe = reflectGetUnsafe();

        // 避开构造方法初始化对象
        M m = (M) unsafe.allocateInstance(M.class);
        m.i = 9;
        System.out.println(m.i);

        // 修改对象成员值
        Field field = M.class.getDeclaredField("i");
        unsafe.putInt(m, unsafe.objectFieldOffset(field), 18);
        System.out.println(m.i);

        // CAS i++
        int i = unsafe.getAndAddInt(m, unsafe.objectFieldOffset(field), 1);
        System.out.println(m.i);
    }

    private static Unsafe reflectGetUnsafe() {
        try {
            // 获得 theUnsafe 属性对象
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            // 取消权限控制检查，让其可获得 private 修饰属性
            field.setAccessible(true);
            // 获得 Unsafe.class 的 theUnsafe 属性（如果底层字段是一个静态字段，则忽略 obj 参数；它可能为 null）
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}